本文档将详细介绍如何使用 Vivado 2021 和 Vitis 2021 通过配置硬件及软件、引脚约束等,在电脑显示屏上通过 HDMI 接口显示出四条彩色条。文中将结合所提供的工程模块硬件设计图、实验结果显示图和系统框图进行说明。
Processor System Reset 模块
作用:该模块用于生成和管理系统复位信号。它确保在系统启动和运行过程中,各个模块能够在正确的时序下进行复位操作,防止系统出现不稳定状态。
AXI Interconnect 模块
作用:AXI Interconnect 模块用于连接多个 AXI(Advanced eXtensible Interface)总线设备。它实现了多个主设备和从设备之间的数据传输和控制,确保数据能够在不同模块之间正确地流动。
AXI Video Direct Memory Access 模块
作用:该模块用于在视频数据和内存之间进行直接内存访问(DMA)操作。它能够高效地处理视频数据的传输,减少 CPU 的负担,提高系统性能。
Video Timing Controller 模块
作用:Video Timing Controller 模块负责生成视频时序信号,如行同步、场同步和像素时钟等。这些信号对于正确地在显示器上显示视频数据至关重要。
VDMA 模块
作用:VDMA(Video DMA)模块用于在视频数据和系统内存之间进行高速数据传输。它能够根据视频时序控制器生成的时序信号,将视频数据从内存中读取出来,并传输到显示器上。
系统框图如下:
PS(Processing System)部分
ARM Cortex - A9:这是系统的主处理器,负责运行软件程序,控制整个系统的运行。
HP 接口和 GP 接口:这些接口用于连接不同的外设,实现数据和控制信号的传输。
DDR 存储器:用于存储系统运行所需的程序和数据,提供高速的数据存储和访问能力。
PL(Programmable Logic)部分
VDMA:与图一中的 VDMA 模块功能相同,负责视频数据的内存访问。
Video Timing Controller:生成视频时序信号,确保视频数据的正确显示。
AXI - Stream to DVI Transmitter:该模块将 AXI - Stream 格式的视频数据转换为 DVI(Digital Visual Interface)格式,以便通过 HDMI 接口传输到显示器上。
HDMI 显示器:用于显示最终的视频输出。
将HDMI 驱动部分封装成 IP 核,以便后续直接导入。
在之前的硬件设计基础上,我们需要添加ZYNQ IP 核的设计:
配置完成后的IP核:
搜索vdma核并按下图进行配置:
搜索timing核并按下图进行配置:
搜索veido out核并按下图进行配置:
搜索clock核并按下图进行配置:
添加自定义IP:dvi_transmitter。该 IP 核位于工程目录下的 ip_repo 文件夹中。
添加完成之后进行连接并引出外部端口(只需要引出 TMDS 端口)。pclk_x5连接到上一步时钟输出的clkout2上。
进行连线,然后点击“Run Connnection Automation”,下面列出了会自动连接的模块及其接口,勾选“All Automation”,然后点击“OK”按钮。此时系统会自动生成 AXI Interconnect(axi_mem_intercon) 和 AXI Interconnect(ps7_0_axi_periph) 两个模块。另外系统也自动生成了 1 个 reset 模块(rst_ps7_0_150M),用于复位总线上的外设。
block design 修改完成后保存,然后重新 Generate Output Products 和“Create HDL Wrapper”。接下来我们还要修改约束文件,根据原理图为 HDMI 接口分配引脚。
保存约束文件,然后进行之后操作重新生成 BIT 文件。
右击创建的平台工程,点击Update Hardware Specification:选择.xsa文件路径,出现以下弹框,点击OK,说明更新成功。好的习惯:更新完之后继续右击平台工程Build一下。
在软件项目中编写代码,在软件代码中,定义四条彩色条(红、绿、蓝、白)的数据。实现数据的生成和传输。
将这些彩色条数据存储在 DDR 存储器中,通过 VDMA 模块将数据传输到显示器上。
x
//VDMA device ID//VTC device ID
XAxiVdma vdma;DisplayCtrl dispCtrl;VideoMode vd_mode;
unsigned int const frame_buffer_addr = (XPAR_PS7_DDR_0_S_AXI_BASEADDR + 0x1000000);
int main(void){ xil_printf("HDMI Display 1920*1080 \r\n");
//set video parameters, resolution: 1920*1080 vd_mode = VMODE_1920x1080;
//configure VDMA run_vdma_frame_buffer(&vdma, VDMA_ID, vd_mode.width, vd_mode.height, frame_buffer_addr,0, 0,ONLY_READ);
//initialize Display controller DisplayInitialize(&dispCtrl, DISP_VTC_ID); //set VideoMode DisplaySetMode(&dispCtrl, &vd_mode); DisplayStart(&dispCtrl);
int y = 0; int x = 0; for(y = 0; y < vd_mode.height; y++) { for(x = 0; x < vd_mode.width; x++) if (x >= 0 && x < (vd_mode.width / 4) * 1) { // white *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+0)=0xff; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+1)=0xff; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+2)=0xff; } else if (x >= (vd_mode.width/4)*1 && x < (vd_mode.width/4)*2) { // red *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+0)=0x00; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+1)=0x00; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+2)=0xff;
} else if (x >= (vd_mode.width/4)*2 && x < (vd_mode.width/4)*3) { // green *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+0)=0x00; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+1)=0xff; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+2)=0x00; } else { // blue *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+0)=0xff; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+1)=0x00; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+2)=0x00; } }
Xil_DCacheFlush(); //flush Cache,update data to DDR while(1) {
} return 0; }
编译工程成功后,用type-c USB线将开发板的JTAG和电脑连接,使用另外一根type-c USB线将开发板的PS UART和电脑连接。使用 HDMI 线将开发板的 HDMI 输出接口连接到电脑显示器的 HDMI 输入接口。
在电脑上打开串口调试工具MobaXterm,和开发板的PS UART建立连接。
在vitis上进入调试模式:在Debug As,选择第一个。全速运行就可以通过串口看到调试信息。
调试结果如下:
运行结果如下: